# -*- coding: utf-8 -*-
"""
    xfree.core.auth.authentication
    ~~~~~~~~~~~~~~~~~~~~~
    文件描述：这个模块定义了与认证相关的抽象基类和异常类。
    作者：xfree
    邮箱：cy_83k@qq.com
"""

from abc import ABC, abstractmethod

from..exceptions import BaseXFreeError


# 异常类
# 当认证提供者决定停止进一步的认证尝试时抛出此异常
class StopAuthentication(BaseXFreeError):
    """
    这个异常用于认证提供者停止进一步的认证尝试。

    :param reason: 字符串类型，表示认证被停止的原因
    """

    def __init__(self, reason):
        # 调用父类的构造函数，传入原因
        super(StopAuthentication, self).__init__(reason)
        self.reason = reason


# 当需要强制用户登出时抛出此异常
class ForceLogout(BaseXFreeError):
    """
    这个异常用于强制用户登出。

    :param reason: 字符串类型，表示用户被强制登出的原因
    """

    def __init__(self, reason):
        # 调用父类的构造函数，传入原因
        super(ForceLogout, self).__init__(reason)
        self.reason = reason


# 抽象基类
# 用于处理整个认证过程的抽象基类
class AuthenticationManager(ABC):
    """
    这是一个用于处理认证过程的抽象基类。已经提供了默认实现，
    不过在需要不同认证流程的情况下，可以使用这个接口来实现自定义的认证管理器。

    如果用户成功通过整个认证过程，应该将用户返回给调用者。
    """

    @abstractmethod
    def authenticate(self, identifier, secret):
        """
        这是一个抽象方法，用于执行认证操作。

        :param identifier: 字符串类型，通常是用户名或电子邮件，用于标识用户
        :param secret: 字符串类型，通常是密码，用于验证用户身份
        :returns: 一个已认证但尚未登录的用户对象
        :rtype: :class:`User<xfree.user.models.User>`
        """
        pass


# 用于提供xfree认证服务的抽象基类
class AuthenticationProvider(ABC):
    """
    这是一个用于为xfree提供认证服务的抽象基类。

    例如，实现者可以选择使用LDAP作为认证源（此处只是示例，未实际实现）。
    """

    @abstractmethod
    def authenticate(self, identifier, secret):
        """
        这是一个抽象方法，用于执行认证操作。

        :param identifier: 字符串类型，通常是用户名或电子邮件，用于标识用户
        :param secret: 字符串类型，通常是密码，用于验证用户身份
        :returns: 一个已认证的用户对象
        :rtype: :class:`User<flask://xfree.user.models.User>`
        """
        pass

    def __call__(self, identifier, secret):
        return self.authenticate(identifier, secret)


# 用于处理认证失败的抽象基类
class AuthenticationFailureHandler(ABC):
    """
    这个抽象基类用于处理认证失败的后处理操作。例如，当没有认证提供者返回用户，
    或者认证提供者抛出 :class:`StopAuthentication<xfree.core.auth.authentication.StopAuthentication>` 异常时。

    后处理操作可以有多种形式，比如增加登录尝试次数、
    如果尝试次数过多则锁定账户、如果用户在不同会话中已认证则强制重新认证等。

    注意，失败处理程序不应该返回值，因为返回值不会被使用。
    """

    @abstractmethod
    def handle_authentication_failure(self, identifier):
        """
        这是一个抽象方法，用于处理认证失败操作。

        :param identifier: 字符串类型，通常是用户名或电子邮件，用于标识用户
        """
        pass

    def __call__(self, identifier):
        self.handle_authentication_failure(identifier)


# 用于处理认证成功后的操作的抽象基类
class PostAuthenticationHandler(ABC):
    """
    这个抽象基类用于处理认证成功后的后处理操作。成功处理器接收通过成功认证返回的用户实例，
    而不是用户标识符。

    后处理器可以决定执行一些操作，比如向用户显示消息、
    清除失败的登录尝试次数等。

    或者，后处理器可以决定通过抛出
    :class:`StopAuthentication<xfree.core.auth.authentication.StopAuthentication>`
    来取消认证过程，例如用户已成功认证但尚未激活其账户的情况。

    取消成功的认证会导致已注册的
    :class:`~xfree.core.auth.authentication.AuthenticationFailureHandler`
    实例被执行。

    同样，成功处理程序不应该返回值，因为返回值不会被使用。
    """

    @abstractmethod
    def handle_post_auth(self, user):
        """
        这是一个抽象方法，用于处理认证成功后的操作。

        :param user: 一个已认证但尚未登录的用户对象
        :type user: :class:`User<xfree.user.model.User>`
        """
        pass

    def __call__(self, user):
        self.handle_post_auth(user)


# 用于处理xfree中重新认证过程的抽象基类
class ReauthenticateManager(ABC):
    """
    这是一个用于处理xfree中重新认证过程的抽象基类。已经提供了默认实现，
    不过在需要不同重新认证流程的情况下，可以使用这个接口来实现自定义的重新认证管理器。

    与AuthenticationManager不同，这里不需要将用户返回给调用者。
    """

    @abstractmethod
    def reauthenticate(self, user, secret):
        """
        这是一个抽象方法，用于执行重新认证操作。

        :param user: 当前用户实例
        :param secret: 字符串类型，用户提供的用于重新认证的秘密信息
        :type user: :class:`User<xfree.user.models.User>`
        """
        pass

    def __call__(self, user, secret):
        pass


# 用于在用户已登录的情况下进行重新认证的抽象基类
class ReauthenticateProvider(ABC):
    """
    这个抽象基类用于在用户已登录的情况下进行重新认证操作。

    ReauthenticateProviders与
    :class:`~xfree.core.auth.authentication.AuthenticationProvider`
    类似，但不同之处在于它们接收用户实例而不是用户标识符。

    成功的重新认证应该返回True，失败则返回None，这样可以让其他提供者有机会尝试。

    如果ReauthenticateProvider确定应该立即结束重新认证过程，
    它可以抛出 :class:~xfree.core.auth.authentication.StopAuthentication`
    异常来安全地结束这个过程。
    """

    @abstractmethod
    def reauthenticate(self, user, secret):
        """
        这是一个抽象方法，用于执行重新认证操作。

        :param user: 当前用户实例
        :param secret: 字符串类型，用户提供的用于重新认证的秘密信息
        :type user: :class:`User<xfree.user.models.User>`
        :returns: 成功重新认证返回True，否则返回None
        """
        pass

    def __call__(self, user, secret):
        self.handle_reauth(user, secret)


# 用于处理重新认证失败的抽象基类
class ReauthenticateFailureHandler(ABC):
    """
    这个抽象基类用于管理xfree中重新认证失败的操作。

    ReauthenticateFailureHandlers与
    :class:`~xfree.core.auth.authentication.AuthenticationFailureHandler`
    类似，但不同之处在于它们接收用户实例而不是用户标识符。
    """

    @abstractmethod
    def handle_reauth_failure(self, user):
        """
        这是一个抽象方法，用于处理重新认证失败操作。

        :param user: 当前用户实例，重新认证尝试失败
        :type user: :class:`User<xfree.user.models.User>`
        """
        pass

    def __call__(self, user):
        self.handle_reauth_failure(user)


# 用于处理成功重新认证后的操作的抽象基类
class PostReauthenticateHandler(ABC):
    """
    这个抽象基类用于处理成功重新认证后的操作。

    PostReauthenticateHandlers与
    :class:`~xfree.core.auth.authentication.PostAuthenticationHandler`
    类似，包括它们通过抛出
    :class:`StopAuthentication<xfree.core.auth.authentication.Stop### Authentication>`
    来取消成功尝试的能力。
    """

    @abstractmethod
    def handle_post_reauth(self, user):
        """
        这是一个抽象方法，用于处理成功重新认证后的操作。

        :param user: 当前用户实例，重新认证尝试成功
        :type user: :class:`User<xfree.user.models.User>`
        """
        pass

    def __call__(self, user):
        self.handle_post_reauth(user)